package com.ruoyi.eqmonitor.dispose.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.eqmonitor.dispose.domain.ExteriorMonitorData;
import com.ruoyi.eqmonitor.dispose.mapper.ExteriorMonitorDataMapper;
import com.ruoyi.eqmonitor.dispose.service.IExteriorMonitorDataService;
import com.ruoyi.eqmonitor.utils.DynamicTableNameHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设备监测时序数据
 */
@Slf4j
@Service
public class ExteriorMonitorDataServiceImpl extends ServiceImpl<ExteriorMonitorDataMapper, ExteriorMonitorData> implements IExteriorMonitorDataService {

    @Override
    public void createMonthTable(String yyyy_mm) {
        log.info("开始创建{}月数据表", yyyy_mm);
        baseMapper.createMonthTable(yyyy_mm);
        log.info("{}月数据表创建成功", yyyy_mm);
    }

    @Override
    public void insert(ExteriorMonitorData monitorData) {
        try {
            String date = DateUtil.format(monitorData.getMonitorTime(), "_yyyy_MM");
            DynamicTableNameHelper.setRequestData("table_suffix", date);
            LambdaQueryWrapper<ExteriorMonitorData> wrpper = Wrappers.lambdaQuery();
            wrpper.eq(ExteriorMonitorData::getSnCode, monitorData.getSnCode());
            wrpper.eq(ExteriorMonitorData::getMonitorCode, monitorData.getMonitorCode());
            wrpper.eq(ExteriorMonitorData::getMonitorTime, monitorData.getMonitorTime());
            // 1. 删除有可能重复的数据
            remove(wrpper);
            // 2. 插入数据
            save(monitorData);
            DynamicTableNameHelper.remove();
        } finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public void insertBeach(List<ExteriorMonitorData> monitorDataList) {
        try {
            // 按月分组
            Map<String, List<ExteriorMonitorData>> collect = monitorDataList
                    .stream()
                    .filter(ObjectUtil::isNotNull)
                    .collect(Collectors.groupingBy(exteriorMonitorData ->
                            DateUtil.format(exteriorMonitorData.getMonitorTime(), "_yyyy_MM")));
            // 按月存储
            for (Map.Entry<String, List<ExteriorMonitorData>> entry : collect.entrySet()) {
                String date = entry.getKey();
                List<ExteriorMonitorData> exteriorMonitorData = entry.getValue();
                DynamicTableNameHelper.setRequestData("table_suffix", date);
                try {
                    saveBatch(exteriorMonitorData);
                }catch (Exception e){
                    log.info("主键重复");
                }
                DynamicTableNameHelper.remove();
            }
        } finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    @Override
    public double getMaxValueBySnCodeAndTime(LocalDateTime start, LocalDateTime end, String snCode) {
        LambdaQueryWrapper<ExteriorMonitorData> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ExteriorMonitorData::getSnCode, snCode)
                .ge(ExteriorMonitorData::getMonitorTime, start)
                .lt(ExteriorMonitorData::getMonitorTime, end)
                .eq(ExteriorMonitorData::getMonitorCode, "0x05D1")
                .select(ExteriorMonitorData::getMaxData);
        ExteriorMonitorData exteriorMonitorData = getOne(queryWrapper);
        return exteriorMonitorData==null?0:exteriorMonitorData.getMaxData();
    }

    @Override
    public long countBySncodeAndTimeAndHalfData(String snCode, LocalDateTime start, LocalDateTime end, double halfData) {
        LambdaQueryWrapper<ExteriorMonitorData> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ExteriorMonitorData::getSnCode, snCode)
                .ge(ExteriorMonitorData::getMonitorTime, start)
                .lt(ExteriorMonitorData::getMonitorTime, end)
                .eq(ExteriorMonitorData::getMonitorCode, "0x05D1")
                .lt(ExteriorMonitorData::getMonitorData, halfData);
        return this.count(queryWrapper);
    }
}
